<?php

class data
{

   protected $fieldsets;
   protected $_data;
   protected $_meta = array();
   protected $_bind = FALSE;
   protected $_url = NULL;
   protected $_href = NULL;
   protected $main_table = NULL;
   protected $translate_table = NULL;
   public $id = NULL;

   public function __construct()
   {
      $this->_data = new stdClass();
      $this->id = NULL;
   }

   public function __get($name)
   {
      if (property_exists($this->_data, $name))
      {
         $lang = request::getLang('currentId');
         return $this->_data->{$name}->value($lang);
      } elseif (method_exists($this, $name))
      {
         return $this->$name();
      }

      return NULL;
   }

   public function __call($method, $lang)
   {
      $lang = $lang !== FALSE && $lang !== NULL ? reset($lang) : NULL;

      if (isset($this->_data->{$method}))
      {
         # Get Source value
         if ($lang === 'src' || $lang === 'source')
         {
            if (property_exists($this->_data->$method, 'src_value'))
            {
               return $this->_data->$method->src_value;
            } else
            {
               return NULL;
            }
         }

         return $this->_data->$method->value($lang);
      }

      return $this->loadFieldset($method);
   }

   public function __isset($name)
   {
      if (property_exists($this->_data, $name) && is_object($this->_data->{$name}))
      {
         return TRUE;
      }

      return FALSE;
   }

   /**
    * Write additional params into Data object
    *
    * @param array $data
    */
   public function setMeta($data)
   {
      if (is_array($data))
      {
         $this->_meta = array_merge($this->_meta, $data);
      }
   }

   public function getMeta($name)
   {
      if (isset($this->_meta[$name]))
         return $this->_meta[$name];
      return NULL;
   }

   protected function loadEmpty($fields)
   {
      if (!empty($fields))
      {
         $this->_data = new stdClass();
         for ($i = 0, $t = sizeof($fields); $i < $t; $i++)
         {
            if ($fields[$i]->fieldset == FALSE)
            {
               $this->_data->{$fields[$i]->alias} = clone $fields[$i];
            }
         }

         return TRUE;
      }

      return FALSE;
   }

   public function load($data, $lang_id = NULL)
   {
      $lang = request::getLang('data', $lang_id); // request::getLang('all');
      //if((!empty($lang_id) && !isset($langs[$lang_id])) || !is_array($data)) return FALSE;
      if ((!empty($lang_id) && $lang_id != $lang['id']) || !is_array($data))
         return FALSE;

      foreach ($data AS $key => $value)
      {
         if (isset($this->_data->{$key}))
         {
            $this->_data->{$key}->normalizeValue($value, $lang_id);
         }
      }
   }

   public function save($data)
   {
      if (empty($data) || empty($this->main_table) || empty($this->translate_table))
      {
         return FALSE;
      }

      $langs = request::getLang('all');
      $sql = array();
      $sql['main'] = array();
      $sql['translate'] = array();
      # Validate data

      foreach ($this->_data AS $alias => $f)
      {
         if (array_key_exists($alias, $data))
         {
            $this->_data->{$alias}->validateInput($data[$alias], $this);
         }

         if (!empty($this->_data->{$alias}->independed))
         {
            # SKIP ADDING DATA INTO SQL BECAUSE INDEPENDED FIELDS ARE SAVED ON ->validateInput METHOD
            continue;
         }

         if ($this->_data->{$alias}->translate)
         {
            foreach ($langs AS $l)
            {
               $sql['translate'][$l['id']][] = '`' . $alias . '` = "' . trim($this->_data->{$alias}->saveValue($l['id'])) . '"';
            }
         } else
         {
            $sql['main'][] = '`' . $alias . '` = "' . trim($this->_data->{$alias}->saveValue()) . '"';
         }
      }

      $sql['main'][] = '`mdate` = NOW()';
      $this->mdate = date('Y-m-d H:i:s');

      return $sql;
   }

   public function trueID()
   {
      if ($this->id)
      {
         return $this->id;
      } else
      {
         $DB = database::getInstance();
         return $DB->DB_GetNextID('id', $this->main_table);
      }
   }

   protected function saveFieldsets($data)
   {
      $fields = $this->getFields();
      foreach ($fields AS $key => $set)
      {
         if ($set->fieldset)
         {
            if (empty($this->fieldsets[$key]))
            {
               if (class_exists($key))
               {
                  $this->fieldsets[$key] = new $key($this);
               } else
               {
                  $this->fieldsets[$key] = new fieldset($key, $this);
               }
            }

            $this->fieldsets[$key]->save($data);
         }
      }
   }

   protected function loadFieldset($name)
   {
      $fields = $this->getFields();

      if (!empty($fields->{$name}) && !empty($fields->{$name}->fieldset))
      {
         if (empty($this->fieldsets[$name]))
         {
            if (class_exists($name))
            {
               $this->fieldsets[$name] = new $name($this);
            } else
            {
               $this->fieldsets[$name] = new fieldset($name, $this);
            }
         }

         return $this->fieldsets[$name]->getData();
      }

      return NULL;
   }

   public function updateProperty($row, $lang = NULL)
   {

      if (property_exists($this, $field->alias))
      {
         $field->normalizeValue($value[$field->alias], $value);
         if ($field->isSystem())
         {
            $this->{$field->alias} = $value[$field->alias];
         } elseif (isset($this->{$field->alias}[$lang]))
         {
            $this->{$field->alias}[$lang] = $value[$field->alias];
         }
      }
   }

   public function delete()
   {
      foreach ($this->_data AS $f)
      {
         $f->sweep();
      }
   }

   /**
    * Get binds data for node
    * 
    * @param string $type - articles|[type] || articles || [type]
    * @return array
    */
   public function bind($type = NULL)
   {
      if ($this->_bind === FALSE)
      {
         $binds = array();
         if (empty($this->id))
            return $binds;
         $this_class_name = get_class($this);
         $DB = database::getInstance();

         # GET BINDED ARTICLES
         $sql = 'SELECT *
         FROM `meccano_binds`
         WHERE `node` = "' . $this->id . '"
         AND `bind_belong` = "a"
         AND `node_belong` = "' . ($this_class_name == 'article' ? 'a' : 'c') . '"';

         $DB->sql = $sql;
         $DB->DB_Fetch();

         for ($i = 0, $t = $DB->rows; $i < $t; $i++)
         {
            $bind = $DB->fetched[$i];
            $binds['articles'][$bind['bind']] = $bind;
         }

         if (!empty($binds['articles']))
         {
            $ids = array_keys($binds['articles']);
            $filter = array('field' => array('id' => array('type' => 'exact', 'value' => $ids)));
            $A = new articles();
            $articles = $A->getArticles($filter);

            $tmp = $binds['articles'];
            $binds['articles'] = FALSE;
            if (!empty($articles))
            {
               foreach ($tmp AS $id => $bind)
               {
                  if (isset($articles[$id]))
                  {
                     $bind['types'] = !empty($bind['types']) ? explode(',', $bind['types']) : array();
                     $binds['articles'][$id] = $articles[$id];
                     $binds['articles'][$id]->setMeta($bind);
                  }
               }
            }
         }

         # GET BINDED CATEGORIES
         $sql = 'SELECT * FROM `meccano_binds`
         WHERE `node_belong` = "' . ($this_class_name == 'article' ? 'a' : 'c') . '"
         AND `node` = ' . $this->id . '
         AND `bind_belong` = "c"
         ORDER BY `position` ASC';

         $DB->sql = $sql;
         $DB->DB_Fetch();
         for ($i = 0, $t = $DB->rows; $i < $t; $i++)
         {
            $bind = $DB->fetched[$i];
            $bind['types'] = !empty($bind['types']) ? explode(',', $bind['types']) : array();
            $binds['categories'][$bind['bind']] = tree_static::getNode($bind['bind']);
            $binds['categories'][$bind['bind']]->setMeta($bind);
         }
         
         $this->_bind = $binds;
      }
      
      $binds = $this->_bind;
      
      if(!empty($type))
      {
         $type    = explode('|', $type);
         $belongs = NULL;

         if($type[0] == 'articles' || $type[0] == 'categories')
         {
            $belongs = $type[0];
            if(!empty($type[1])) $type = $type[1];
            else                 $type = NULL;
         } else
         {
            $type = $type[0];
         }
         
         $KERNEL = kernel::getInstance();
         $types = $KERNEL->getTypes('b');
         
         if(!empty($type) && in_array($type, $types))
         {
            $type = array_search($type, $types);

            if(!empty($binds['articles']) && ($belongs === NULL || $belongs == 'articles'))
            {
               $tmp = array();
               foreach($binds['articles'] AS $v)
               {
                  $v_types = $v->getMeta('types');
                  if(in_array($type, $v_types))
                  {
                     $tmp[$v->id] = $v;
                  }
               }
               $binds['articles'] = $tmp;
            }
            
            if(!empty($binds['categories']) && ($belongs === NULL || $belongs == 'categories'))
            {
               $tmp = array();
               foreach($binds['categories'] AS $v)
               {
                  $v_types = $v->getMeta('types');
                  if(in_array($type, $v_types))
                  {
                     $tmp[$v->id] = $v;
                  }
               }
               $binds['categories'] = $tmp;
            }
         }
         
         if(!empty($belongs))
         {
            $binds = empty($binds[$belongs]) ? array() : $binds[$belongs];
         }
      }
      
      return $binds;
   }

   public function tags()
   {
      return tags::getAssignedTags($this->id);
   }

   public function comments()
   {
      if (!empty($this->id))
      {
         $COMMENTS = new comments();
         return $COMMENTS->load($this->id, TRUE);
      }

      return FALSE;
   }

   public function getFields($node = 0, $filter = array())
   {
      $FIELDS = fields::getInstance();
      return $FIELDS->getFields($node, $filter);
   }

   public function href()
   {
      # JUST INTERFACE, SHOULD BE IMPLEMENTED IN EXTENDING CLASSES
   }

   public function url()
   {
      # JUST INTERFACE, SHOULD BE IMPLEMENTED IN EXTENDING CLASSES
   }
}